package org.vacoor.xqq.ui.comp.combo;

import org.vacoor.xqq.ui.comp.border.RolloverBorder;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.ComboPopup;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

/**
 * @author Vacoor
 */
public class IconifyItemComboBoxUI extends BasicComboBoxUI {

    private Handler handler;

    /**
     * 显示或隐藏 Popup 按钮
     */
    @Override
    protected JButton createArrowButton() {
        JButton button = new ArrowButton();
        button.setName("ComboBox.arrowButton");
        return button;
    }

    /**
     * 输入框
     */
    @Override
    protected ComboBoxEditor createEditor() {
        return !(comboBox instanceof IconifyComboBox) ? super.createEditor() : new IconifyComboBoxEditor();
//        return super.createEditor();
    }

    /**
     * 使用 Renderer 无法实现带按钮的 List 另外可变高度也不好搞, 这里直接重写 Popup菜单
     */
    @Override
    protected ComboPopup createPopup() {
        return !(comboBox instanceof IconifyComboBox) ? super.createPopup() : new IconifyComboBoxPopup((IconifyComboBox) comboBox);
//        return super.createPopup();
    }

    /**
     * Popup 菜单中 JList 及禁用编辑时使用的渲染器, 上面替换了 Popup 所以这里没用了
     */
    @Override
    protected ListCellRenderer createRenderer() {
        return super.createRenderer();
//        return new IconifyComboBoxRenderer();
    }

    @Override
    protected void installDefaults() {
        super.installDefaults();
        comboBox.setBorder(
                new RolloverBorder(
                        BorderFactory.createCompoundBorder(
                                BorderFactory.createEmptyBorder(1, 1, 1, 1),
                                new LineBorder(new Color(167, 195, 212), 1, true)
                        ),
                        BorderFactory.createCompoundBorder(
                                new LineBorder(new Color(96, 200, 253), 1, true),
                                new LineBorder(new Color(51, 139, 192), 1, true))
                )
        );
    }

    @Override
    protected FocusListener createFocusListener() {
        return getHandler();
    }

    @Override
    protected void configureEditor() {
        super.configureEditor();
        ComboBoxEditor editor = comboBox.getEditor();
        if (!(editor instanceof IconifyComboBoxEditor)) {
            return;
        }
        this.editor.setFocusable(false);
        JTextField ed = ((IconifyComboBoxEditor) editor).getInnerTextField();
        ed.addFocusListener(getHandler());

        Border border = comboBox.getBorder();
        if (border instanceof RolloverBorder) {
            ((RolloverBorder) border).addTrigger(ed);
        }
    }

    @Override
    public void configureArrowButton() {
        super.configureArrowButton();
        Border border = comboBox.getBorder();
        if (border instanceof RolloverBorder) {
            ((RolloverBorder) border).addTrigger(arrowButton);
        }
    }

    private Handler getHandler() {
        if (handler == null) {
            handler = new Handler();
        }
        return handler;
    }

    private class Handler implements FocusListener {

        public void focusGained(FocusEvent e) {
            ComboBoxEditor editor = comboBox.getEditor();

            if ((editor != null) && (e.getSource() == editor.getEditorComponent())) {
                return;
            }
            hasFocus = true;
            comboBox.repaint();

            if (comboBox.isEditable() && IconifyItemComboBoxUI.this.editor != null) {
                IconifyItemComboBoxUI.this.editor.requestFocus();
            }
        }

        public void focusLost(FocusEvent e) {
            IconifyComboBoxEditor editor = (IconifyComboBoxEditor) comboBox.getEditor();
            if ((editor != null) && (e.getSource() == editor.getInnerTextField())) {
                Object item = editor.getItem();

                Object selectedItem = comboBox.getSelectedItem();
                if (!e.isTemporary() && item != null && !item.equals((selectedItem == null) ? "" : selectedItem)) {
                    comboBox.actionPerformed(new ActionEvent(editor, 0, "", EventQueue.getMostRecentEventTime(), 0));
                }
            }

            hasFocus = false;
            if (!e.isTemporary()) {
                setPopupVisible(comboBox, false);
            }
            comboBox.repaint();
        }
    }
}